Chapters ▾ 2nd Edition

6.2 GitHub (گیت هاب) - Contributing to a Project (مشارکت در یک پروژه)

Contributing to a Project (مشارکت در یک پروژه)

حالا که حساب کاربری ما آماده شده است، بیایید به بررسی برخی جزئیات بپردازیم که می‌توانند هنگام مشارکت در یک پروژه موجود مفید باشند.

Forking Projects (فورک کردن پروژه‌ها)

اگر می‌خواهید در یک پروژه‌ی موجود مشارکت کنید اما دسترسی «push» به آن ندارید، می‌توانید پروژه را «fork» کنید. وقتی یک پروژه را «fork» می‌کنید، GitHub یک نسخه‌ی کامل از آن پروژه برای شما ایجاد می‌کند؛ این نسخه در فضای کاربری شما قرار می‌گیرد و شما می‌توانید به آن push کنید.

یادداشت

از گذشته، واژه «fork» گاهی بار معنایی منفی داشته است؛ به این معنا که کسی یک پروژه متن‌باز را به مسیر دیگری برده و گاهی یک پروژه رقیب ایجاد کرده که باعث تقسیم مشارکت‌کنندگان شده است. اما در «GitHub، «fork صرفاً همان پروژه است که در فضای کاربری شما قرار می‌گیرد و به شما امکان می‌دهد تغییراتی را به صورت عمومی روی پروژه اعمال کنید تا به روشی بازتر مشارکت کنید.

به این ترتیب، پروژه‌ها نیازی ندارند که کاربران را به‌عنوان همکار اضافه کنند تا دسترسی push بدهند. افراد می‌توانند پروژه را فورک کنند، تغییرات خود را روی آن push کنند و سپس با ایجاد چیزی به نام Pull Request، تغییراتشان را به مخزن اصلی بازگردانند که در ادامه به آن می‌پردازیم. این کار یک بحث و بررسی کد را باز می‌کند و مالک پروژه و مشارکت‌کننده می‌توانند درباره تغییرات گفتگو کنند تا زمانی که مالک از تغییر راضی شود و سپس آن را با پروژه اصلی ادغام (merge) کند.

برای فورک کردن یک پروژه، به صفحه پروژه مراجعه کنید و روی دکمه «Fork» که در بالای سمت راست صفحه قرار دارد کلیک کنید.

The ``Fork'' button.
نمودار 89. The “Fork” button.

بعد از چند ثانیه، به صفحه پروژه جدید خود هدایت می‌شوید که نسخه‌ای قابل ویرایش از کد در اختیار شماست.

The GitHub Flow (جریان کاری گیتهاب)

GitHub بر اساس یک روند همکاری خاص طراحی شده که محور آن Pull Requestها است. این روند چه در همکاری با یک تیم کوچک و متمرکز در یک مخزن مشترک، و چه در همکاری یک شرکت جهانی یا شبکه‌ای از افراد ناشناس که از طریق ده‌ها فورک مشارکت می‌کنند، کاربرد دارد. این روش مبتنی بر روند کاری شاخه‌های موضوعی است که در شاخه‌سازی در گیت توضیح داده شده است.

روند کلی به این صورت است:

۱. پروژه را فورک کنید.
۲. یک شاخه موضوعی (topic branch) از شاخه master بسازید.
۳. چند کامیت برای بهبود پروژه انجام دهید.
۴. این شاخه را به پروژه GitHub خود push کنید.
۵. یک Pull Request در GitHub باز کنید.
۶. درباره آن بحث کنید و در صورت نیاز کامیت‌های بیشتری بزنید.
۷. مالک پروژه Pull Request را ادغام (merge) یا بسته (close) می‌کند.
۸. شاخه master به‌روزشده را دوباره با فورک خود همگام (sync) کنید.

این در واقع همان روند کاری مدیر ادغام (Integration Manager) است که در روند کاری مدیر-یکپارچه‌سازی توضیح داده شده، اما به جای استفاده از ایمیل برای ارتباط و بررسی تغییرات، تیم‌ها از ابزارهای وب‌محور GitHub استفاده می‌کنند.

حالا بیایید با هم یک مثال از پیشنهاد تغییر در یک پروژه متن‌باز که روی GitHub میزبانی شده را با استفاده از این روند مرور کنیم.

Creating a Pull Request (ایجاد یک Pull Request)

تونی به دنبال کدی برای اجرای روی میکروکنترلر قابل برنامه‌ریزی Arduino خود است و یک فایل برنامه عالی در GitHub به آدرس https://github.com/schacon/blink پیدا کرده است.

The project we want to contribute to.
نمودار 90. The project we want to contribute to.

تنها مشکلی که وجود دارد این است که نرخ چشمک‌زدن خیلی سریع است. ما فکر می‌کنیم بهتر است به جای ۱ ثانیه، بین هر تغییر وضعیت ۳ ثانیه صبر کنیم. پس بیایید برنامه را بهبود دهیم و تغییر پیشنهادی خود را به پروژه ارسال کنیم.

ابتدا، همان‌طور که قبلاً گفتیم، روی دکمه «Fork» کلیک می‌کنیم تا نسخه‌ای از پروژه در حساب خودمان داشته باشیم. نام کاربری ما در اینجا «tonychacon» است، پس نسخه پروژه ما در آدرس https://github.com/tonychacon/blink قرار دارد و می‌توانیم آن را ویرایش کنیم. سپس آن را به صورت محلی کلون می‌کنیم، یک شاخه موضوعی ایجاد می‌کنیم، تغییرات کد را اعمال می‌کنیم و در نهایت این تغییرات را دوباره به GitHub ارسال می‌کنیم.

$ git clone https://github.com/tonychacon/blink (1)
Cloning into 'blink'...

$ cd blink
$ git checkout -b slow-blink (2)
Switched to a new branch 'slow-blink'

$ sed -i '' 's/1000/3000/' blink.ino (macOS) (3)
# If you're on a Linux system, do this instead:
# $ sed -i 's/1000/3000/' blink.ino (3)

$ git diff --word-diff (4)
diff --git a/blink.ino b/blink.ino
index 15b9911..a6cc5a5 100644
--- a/blink.ino
+++ b/blink.ino
@@ -18,7 +18,7 @@ void setup() {
// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  [-delay(1000);-]{+delay(3000);+}               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  [-delay(1000);-]{+delay(3000);+}               // wait for a second
}

$ git commit -a -m 'Change delay to 3 seconds' (5)
[slow-blink 5ca509d] Change delay to 3 seconds
 1 file changed, 2 insertions(+), 2 deletions(-)

$ git push origin slow-blink (6)
Username for 'https://github.com': tonychacon
Password for 'https://tonychacon@github.com':
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 340 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To https://github.com/tonychacon/blink
 * [new branch]      slow-blink -> slow-blink
  1. فورک پروژه را به‌صورت محلی کلون کنید

  2. یک شاخه موضوعی با نامی توصیفی بسازید

  3. تغییرات مورد نظر را در کد اعمال کنید

  4. بررسی کنید که تغییرات به درستی انجام شده‌اند

  5. تغییرات را به شاخه موضوعی کامیت کنید

  6. شاخه موضوعی جدید را به فورک خود در GitHub ارسال (push) کنید

حالا اگر به فورک خود در GitHub برگردیم، می‌بینیم که GitHub متوجه شده یک شاخه موضوعی جدید ارسال کرده‌ایم و یک دکمه بزرگ سبز رنگ به ما نشان می‌دهد تا تغییرات را بررسی کنیم و یک Pull Request به پروژه اصلی باز کنیم.

همچنین می‌توانید به صفحه «Branches» به آدرس https://github.com/<user>/<project>/branches بروید، شاخه خود را پیدا کنید و از آنجا یک Pull Request جدید باز کنید.

Pull Request button
نمودار 91. Pull Request button

اگر روی آن دکمه سبز کلیک کنیم، به صفحه‌ای منتقل می‌شویم که از ما می‌خواهد برای Pull Request خود یک عنوان و توضیح وارد کنیم. تقریباً همیشه ارزشش را دارد که کمی زمان صرف این کار کنیم، چون یک توضیح خوب به مالک پروژه اصلی کمک می‌کند متوجه شود شما قصد انجام چه کاری را داشته‌اید، آیا تغییرات پیشنهادی‌تان درست هستند و این‌که آیا پذیرفتن این تغییرات باعث بهبود پروژه می‌شود یا نه.

همچنین، فهرستی از کامیت‌های موجود در شاخه موضوعی خود می‌بینیم که از شاخه master جلوتر هستند (در این مثال فقط یکی) و یک نمای کلی (diff) از تمام تغییراتی که در صورت ادغام این شاخه توسط مالک پروژه اعمال خواهند شد.

Pull Request creation
نمودار 92. Pull Request creation page

وقتی روی دکمه Create pull request در این صفحه کلیک می‌کنید، مالک پروژه‌ای که آن را فورک کرده‌اید، یک اعلان دریافت می‌کند که کسی در حال پیشنهاد یک تغییر است. این اعلان لینکی به صفحه‌ای خواهد داشت که تمام این اطلاعات — شامل عنوان، توضیحات، لیست کامیت‌ها و تغییرات کد — در آن نمایش داده می‌شود.

یادداشت

اگرچه Pull Request ها معمولاً در پروژه‌های عمومی برای زمانی استفاده می‌شوند که مشارکت‌کننده یک تغییر کامل و آماده برای اعمال دارد، اما در پروژه‌های داخلی نیز از ابتدای چرخه توسعه بسیار کاربرد دارند. از آنجا که حتی بعد از باز کردن Pull Request هم می‌توان به شاخه موضوعی کامیت‌های جدید اضافه کرد، معمولاً Pull Request زودتر باز می‌شود و به عنوان بستری برای همکاری و تکمیل تدریجی کار در قالب یک گفت‌وگو میان اعضای تیم استفاده می‌شود — نه فقط در پایان فرآیند توسعه.

Iterating on a Pull Request (تکرار و بهبود روی یک Pull Request)

در این مرحله، مالک پروژه می‌تواند تغییر پیشنهادی را بررسی کرده و آن را ادغام کند، رد کند یا درباره‌اش نظر بدهد. فرض کنیم او ایده را می‌پسندد، اما ترجیح می‌دهد زمانی که چراغ خاموش است کمی بیشتر از زمانی باشد که روشن است.

در حالی‌ که در روندهای کاری مطرح‌شده در گیت توزیع‌شده این مکالمه ممکن است از طریق ایمیل انجام شود، در GitHub این گفت‌وگو به صورت آنلاین اتفاق می‌افتد. مالک پروژه می‌تواند تفاوت‌های کد (diff) را بررسی کرده و با کلیک روی هر خط، نظر یا بازخورد خود را ثبت کند.

PR line comment
نمودار 93. Comment on a specific line of code in a Pull Request

وقتی نگه‌دارنده (maintainer) این نظر را ثبت می‌کند، فردی که Pull Request را باز کرده (و حتی هر شخص دیگری که مخزن را دنبال می‌کند) یک اعلان دریافت خواهد کرد. بعداً درباره تنظیمات این اعلان‌ها بیشتر صحبت خواهیم کرد، اما اگر تونی اعلان‌های ایمیلی را فعال کرده باشد، ایمیلی شبیه به این دریافت خواهد کرد:

Email notification
نمودار 94. Comments sent as email notifications

هر کسی می‌تواند نظرات کلی نیز در Pull Request ثبت کند. در Pull Request discussion page می‌توانیم مثالی ببینیم که در آن مالک پروژه هم روی یک خط از کد نظر داده و هم یک نظر کلی در بخش گفت‌وگو (discussion) گذاشته است. همچنین می‌بینید که نظرات مربوط به خطوط کد نیز به صورت خودکار وارد جریان گفت‌وگو می‌شوند.

PR discussion page
نمودار 95. Pull Request discussion page

اکنون مشارکت‌کننده می‌تواند ببیند برای پذیرفته شدن تغییراتش چه کاری باید انجام دهد. خوشبختانه این کار در GitHub بسیار ساده است. در حالی که در روش‌های مبتنی بر ایمیل ممکن است مجبور شوید مجموعه‌ی تغییرات خود را دوباره ایجاد کرده و مجدداً به لیست پستی ارسال کنید، در GitHub فقط کافی‌ است کامیت جدیدی به همان شاخه موضوعی اضافه کرده و آن را push کنید؛ این کار به‌صورت خودکار Pull Request را به‌روزرسانی می‌کند.

در Pull Request final همچنین می‌بینید که نظر قدیمی روی کد اکنون مخفی شده، چون آن خط از کد بعد از کامیت جدید تغییر کرده است.

افزودن کامیت جدید به یک Pull Request موجود، اعلان (notification) جدیدی ایجاد نمی‌کند؛ بنابراین تونی تصمیم می‌گیرد یک نظر جدید ثبت کند تا به مالک پروژه اطلاع دهد که تغییرات خواسته‌شده را اعمال کرده است.

PR final
نمودار 96. Pull Request final

نکته جالبی که باید به آن توجه کرد این است که اگر روی تب «Files Changed» در Pull Request کلیک کنید، GitHub به شما یک diff یکپارچه (unified diff) نمایش می‌دهد — یعنی کل تفاوت‌هایی که در صورت ادغام این شاخه موضوعی با شاخه اصلی (main/master)، وارد پروژه خواهند شد. از منظر دستورات Git، این دقیقاً معادل اجرای git diff master…​<branch> است. برای اطلاعات بیشتر درباره این نوع diff، به بخش تشخیص تغییرات معرفی شده مراجعه کنید.

نکته دیگر این است که GitHub بررسی می‌کند که آیا Pull Request بدون تعارض (conflict) قابل ادغام است یا نه، و در صورت امکان، دکمه‌ای برای ادغام مستقیم روی سرور در اختیارتان می‌گذارد. این دکمه فقط زمانی نمایش داده می‌شود که شما دسترسی نوشتن (write access) به مخزن داشته باشید و ادغام به‌صورت ساده (trivial) ممکن باشد. اگر روی این دکمه کلیک کنید، GitHub یک ادغام «غیر fast-forward» انجام می‌دهد — یعنی حتی اگر ادغام می‌توانست به‌صورت fast-forward باشد، باز هم یک commit ادغام (merge commit) ایجاد می‌کند.

البته اگر ترجیح می‌دهید، می‌توانید شاخه را روی سیستم خودتان دریافت (pull) و به صورت محلی ادغام (merge) کنید. اگر این شاخه را در شاخه master ادغام کرده و سپس به GitHub push کنید، Pull Request به‌صورت خودکار بسته خواهد شد.

این همان روند کاری پایه‌ای است که اکثر پروژه‌های GitHub از آن استفاده می‌کنند: شاخه‌های موضوعی ایجاد می‌شوند، روی آن‌ها Pull Request باز می‌شود، گفت‌وگو صورت می‌گیرد، شاید کار بیشتری روی شاخه انجام شود و در نهایت یا درخواست ادغام می‌شود یا بسته می‌گردد.

یادداشت
Not Only Forks

نکته مهمی که باید به آن توجه کرد این است که شما می‌توانید بین دو شاخه در یک مخزن (repository) یک Pull Request باز کنید. اگر در حال کار روی یک ویژگی (feature) با فردی دیگر هستید و هر دوی شما دسترسی نوشتن (write access) به پروژه دارید، می‌توانید یک شاخه موضوعی (topic branch) را در همان مخزن push کرده و روی آن به شاخه master همان پروژه یک Pull Request باز کنید تا فرآیند بازبینی کد (code review) و گفت‌وگو آغاز شود.

در این حالت، نیازی به fork کردن پروژه نیست.

Advanced Pull Requests (Pull Request های پیشرفته)

حالا که با اصول اولیه مشارکت در یک پروژه روی GitHub آشنا شدیم، بیایید به چند نکته و ترفند جالب درباره Pull Request‌ها بپردازیم تا بتوانید مؤثرتر و حرفه‌ای‌تر از آن‌ها استفاده کنید.

Pull Requests as Patches (Pull Request ها به عنوان پچ ها)

مهم است بدانید که بسیاری از پروژه‌ها Pull Request ها را به عنوان صفی از پچ‌های کامل و بدون نقص که باید به ترتیب و بدون مشکل اعمال شوند، نگاه نمی‌کنند—برخلاف پروژه‌های مبتنی بر لیست ایمیل که معمولاً مشارکت‌ها را به صورت سری پچ‌ها (patch series) می‌بینند. اکثر پروژه‌های GitHub شاخه‌های Pull Request را به عنوان گفتگوهای تکرارشونده و تدریجی درباره یک تغییر پیشنهادی در نظر می‌گیرند که در نهایت منجر به یک diff یکپارچه می‌شود که با ادغام (merge) اعمال خواهد شد.

این تفاوت مهم است، چون معمولاً تغییرات قبل از اینکه کد کامل و بی‌نقص باشد پیشنهاد داده می‌شوند—که این موضوع در پروژه‌های مبتنی بر لیست ایمیل کمتر دیده می‌شود. این روند اجازه می‌دهد گفت‌وگو با نگه‌دارنده‌ها (maintainers) زودتر شروع شود تا رسیدن به راه‌حل مناسب بیشتر به یک تلاش جمعی تبدیل شود. وقتی کدی با Pull Request پیشنهاد می‌شود و نگه‌دارنده‌ها یا جامعه تغییراتی را پیشنهاد می‌دهند، معمولاً سری پچ‌ها دوباره ساخته نمی‌شود، بلکه تغییرات به صورت کامیت‌های جدید به همان شاخه اضافه می‌شود و بحث با زمینه کار قبلی ادامه پیدا می‌کند.

برای مثال، اگر به Pull Request final بازگردید، متوجه می‌شوید که مشارکت‌کننده کامیت خود را دوباره بازسازی (rebase) نکرده و Pull Request جدیدی نفرستاده است. بلکه کامیت‌های جدید اضافه کرده و آن‌ها را به شاخه موجود push کرده است. به این ترتیب، اگر در آینده به این Pull Request نگاه کنید، می‌توانید به سادگی تمام زمینه‌ها و دلایل تصمیم‌گیری‌ها را دنبال کنید. فشردن دکمه «Merge» در سایت به طور هدفمند یک کامیت ادغام ایجاد می‌کند که به Pull Request ارجاع می‌دهد تا در صورت نیاز، بررسی گفت‌وگوی اصلی آسان باشد.

Keeping up with Upstream (همگام‌سازی با مخزن اصلی)

اگر Pull Request شما قدیمی شود یا به‌درستی ادغام (merge) نشود، باید آن را اصلاح کنید تا نگه‌دارنده بتواند به‌راحتی آن را ادغام کند. GitHub این موضوع را برای شما بررسی می‌کند و در پایین هر Pull Request به شما اطلاع می‌دهد که آیا ادغام به‌سادگی قابل انجام است یا خیر.

PR merge failure
نمودار 97. Pull Request does not merge cleanly

اگر چیزی مثل Pull Request does not merge cleanly ببینید، باید شاخه خود را اصلاح کنید تا وضعیت آن سبز شود و نگه‌دارنده مجبور به انجام کار اضافی نباشد.

برای این کار دو راه اصلی دارید: ۱. می‌توانید شاخه خود را روی شاخه هدف (معمولاً شاخه master مخزن اصلی که فورک کرده‌اید) ری‌بیس (rebase) کنید، ۲. یا شاخه هدف را وارد (merge) شاخه خود کنید.

اکثر توسعه‌دهندگان در GitHub روش دوم را انتخاب می‌کنند، به دلایلی که در بخش قبلی توضیح داده شد. مهم تاریخچه و ادغام نهایی است؛ پس ری‌بیس تنها تاریخچه را کمی مرتب‌تر می‌کند اما در عوض بسیار دشوارتر و مستعد خطا است.

اگر می‌خواهید شاخه هدف را وارد شاخه خود کنید تا Pull Request شما قابل ادغام شود، باید مخزن اصلی را به عنوان یک remote جدید اضافه کنید، از آن fetch بگیرید، شاخه اصلی آن مخزن را با شاخه موضوعی خود merge کنید، مشکلات احتمالی را رفع کنید و در نهایت آن را دوباره به همان شاخه‌ای که Pull Request را باز کرده‌اید push کنید.

مثلاً فرض کنید در مثال «tonychacon» که قبلاً استفاده کردیم، نویسنده اصلی تغییراتی داده که باعث ایجاد تعارض در Pull Request می‌شود. بیایید قدم به قدم این مراحل را بررسی کنیم.

$ git remote add upstream https://github.com/schacon/blink (1)

$ git fetch upstream (2)
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
Unpacking objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
From https://github.com/schacon/blink
 * [new branch]      master     -> upstream/master

$ git merge upstream/master (3)
Auto-merging blink.ino
CONFLICT (content): Merge conflict in blink.ino
Automatic merge failed; fix conflicts and then commit the result.

$ vim blink.ino (4)
$ git add blink.ino
$ git commit
[slow-blink 3c8d735] Merge remote-tracking branch 'upstream/master' \
    into slower-blink

$ git push origin slow-blink (5)
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 682 bytes | 0 bytes/s, done.
Total 6 (delta 2), reused 0 (delta 0)
To https://github.com/tonychacon/blink
   ef4725c..3c8d735  slower-blink -> slow-blink
  1. مخزن اصلی را به‌عنوان یک remote با نام «upstream» اضافه کنید

  2. جدیدترین تغییرات را از آن remote دریافت (fetch) کنید

  3. شاخه اصلی آن مخزن را وارد (merge) شاخه موضوعی خود کنید

  4. تعارض‌های به‌وجود آمده را رفع کنید

  5. تغییرات را دوباره به همان شاخه موضوعی در مخزن خود push کنید

به‌محض انجام این کار، Pull Request به‌صورت خودکار به‌روزرسانی شده و دوباره بررسی می‌شود تا مشخص شود آیا به‌درستی قابل ادغام است یا خیر.

PR fixed
نمودار 98. Pull Request now merges cleanly

یکی از ویژگی‌های عالی Git این است که می‌توانید این کار را به‌صورت مداوم انجام دهید. اگر پروژه‌ی شما طولانی‌مدت است، می‌توانید بارها و بارها شاخه هدف را با شاخه خود ادغام کنید و تنها با تعارض‌هایی که از آخرین ادغام به بعد رخ داده‌اند برخورد کنید، که این روند را بسیار قابل مدیریت می‌کند.

اگر واقعاً می‌خواهید شاخه را با rebase تمیز کنید، قطعاً می‌توانید این کار را انجام دهید، اما بسیار توصیه می‌شود که روی همان شاخه‌ای که Pull Request باز شده است، force push نکنید. چون اگر دیگران آن شاخه را pull کرده و روی آن کار بیشتری انجام داده باشند، با مشکلاتی که در خطرات ریبیس‌کردن توضیح داده شده مواجه می‌شوید. در عوض، شاخه rebase شده را روی یک شاخه جدید در GitHub push کنید و یک Pull Request جدید باز کنید که به Pull Request قبلی ارجاع دهد، سپس Pull Request اصلی را ببندید.

References (منابع)

سؤال بعدی شما ممکن است این باشد: «چطور می‌توانم به Pull Request قدیمی ارجاع بدهم؟» در واقع، روش‌های بسیار زیادی وجود دارد تا تقریباً در هر جایی که بتوانید در گیت‌هاب بنویسید، به موارد دیگر ارجاع دهید.

بیایید با نحوه ارجاع متقابل به یک Pull Request یا Issue دیگر شروع کنیم. تمام Pull Requestها و Issueها شماره‌ای اختصاص داده شده دارند که در هر پروژه منحصر به فرد است. برای مثال، نمی‌توانید هم Pull Request شماره ۳ و هم Issue شماره ۳ داشته باشید. اگر بخواهید به هر Pull Request یا Issue از هر جای دیگر ارجاع دهید، کافی است در هر نظر یا توضیحی عبارت <شماره> را بنویسید. اگر Issue یا Pull Request در جای دیگری قرار دارد، می‌توانید دقیق‌تر باشید؛ مثلاً اگر به یک Issue یا Pull Request در یک فورک از مخزن فعلی اشاره می‌کنید، به شکل username<شماره> بنویسید، یا اگر می‌خواهید به چیزی در یک مخزن کاملاً متفاوت ارجاع دهید، از username/repo#<شماره> استفاده کنید.

بیایید یک مثال ببینیم. فرض کنید شاخه را روی پایه جدید بازبیس کردیم، یک Pull Request جدید برای آن ساختیم و حالا می‌خواهیم به Pull Request قدیمی از جدید ارجاع دهیم. همچنین می‌خواهیم به یک Issue در فورک مخزن و یک Issue در یک پروژه کاملاً متفاوت اشاره کنیم. می‌توانیم توضیحات را دقیقاً مثل Cross references in a Pull Request. پر کنیم.

PR references
نمودار 99. Cross references in a Pull Request.

وقتی این Pull Request را ارسال کنیم، همه این‌ها به صورت Cross references rendered in a Pull Request. نمایش داده خواهند شد.

PR references rendered
نمودار 100. Cross references rendered in a Pull Request.

توجه کنید که آدرس کامل گیت‌هاب که آنجا گذاشتیم، به اطلاعات لازم و کوتاه‌شده تبدیل شده است.

حالا اگر تونی به عقب برگردد و Pull Request اصلی را ببندد، با اشاره به آن در Pull Request جدید، گیت‌هاب به‌طور خودکار یک رویداد بازخورد (trackback) در خط زمانی آن Pull Request ایجاد می‌کند. این یعنی هر کسی که به این Pull Request مراجعه کند و ببیند بسته شده، به راحتی می‌تواند به آن Pull Request که جایگزین شده لینک بزند. این لینک چیزی شبیه به Link back to the new Pull Request in the closed Pull Request timeline. خواهد بود.

PR closed
نمودار 101. Link back to the new Pull Request in the closed Pull Request timeline.

علاوه بر شماره‌های Issue، می‌توانید به یک کامیت خاص با استفاده از SHA-1 هم ارجاع دهید. باید SHA-1 کامل ۴۰ حرفی را مشخص کنید، اما اگر گیت‌هاب این مقدار را در یک کامنت ببیند، به‌طور مستقیم به همان کامیت لینک می‌دهد. دوباره، می‌توانید به کامیت‌ها در فورک‌ها یا مخازن دیگر به همان روشی که برای Issue ها انجام دادید، ارجاع بدهید.

GitHub Flavored Markdown (مارک‌داون با طعم گیتهاب)

ارجاع دادن به Issue های دیگر فقط شروع کارهای جالبی است که می‌توانید در تقریباً هر کادر متنی در گیت‌هاب انجام دهید. در توضیحات Issue و Pull Request، نظرات، کامنت‌های کد و موارد دیگر، می‌توانید از چیزی استفاده کنید که «مارک‌داون با طعم گیت‌هاب» نامیده می‌شود. مارک‌داون مثل نوشتن متن ساده است، اما به صورت غنی و زیبا نمایش داده می‌شود.

برای دیدن نمونه‌ای از اینکه چگونه نظرات یا متن‌ها می‌توانند با مارک‌داون نوشته و سپس به شکل زیبا نمایش داده شوند، به An example of GitHub Flavored Markdown as written and as rendered. مراجعه کنید.

Example Markdown
نمودار 102. An example of GitHub Flavored Markdown as written and as rendered.

نسخه گیت‌هاب از مارک‌داون امکانات بیشتری نسبت به نحو پایه مارک‌داون اضافه می‌کند. تمام این قابلیت‌ها هنگام نوشتن نظرات یا توضیحات مفید برای Pull Request یا Issue می‌توانند بسیار کاربردی باشند.

Task Lists (لیست تسک ها)

اولین قابلیت بسیار کاربردی مارک‌داون مخصوص گیت‌هاب، به‌ویژه برای استفاده در Pull Request ها، لیست کارها (Task List) است. لیست کارها فهرستی از گزینه‌های قابل تیک زدن است که نشان‌دهنده کارهایی است که می‌خواهید انجام دهید. قرار دادن این لیست‌ها در یک Issue یا Pull Request معمولاً به این معناست که این موارد باید قبل از اینکه آن مورد را کامل شده در نظر بگیرید، انجام شوند.

شما می‌توانید یک لیست کارها به این شکل ایجاد کنید:

- [X] Write the code
- [ ] Write all the tests
- [ ] Document the code

اگر این را در توضیحات Pull Request یا Issue خود بگذاریم، به صورت Task lists rendered in a Markdown comment. نمایش داده خواهد شد.

Example Task List
نمودار 103. Task lists rendered in a Markdown comment.

این قابلیت معمولاً در Pull Request ها استفاده می‌شود تا نشان دهد که قبل از آماده شدن Pull Request برای ادغام، چه کارهایی روی شاخه باید انجام شود. قسمت جالب ماجرا این است که می‌توانید به سادگی با کلیک روی چک‌باکس‌ها نظر را به‌روزرسانی کنید — نیازی نیست خود مارک‌داون را مستقیماً ویرایش کنید تا تسک‌ها علامت‌گذاری شوند.

علاوه بر این، گیت‌هاب در Issue ها و Pull Request های شما به دنبال لیست‌های کار می‌گردد و آن‌ها را به عنوان متادیتا روی صفحاتی که آن‌ها را فهرست می‌کنند نمایش می‌دهد. برای مثال، اگر یک Pull Request با لیست کار داشته باشید و صفحه کلی تمام Pull Request ها را ببینید، می‌توانید پیشرفت انجام آن را مشاهده کنید. این به افراد کمک می‌کند تا Pull Request ها را به زیرکارها تقسیم کنند و دیگران هم پیشرفت شاخه را دنبال کنند. یک نمونه از این مورد را می‌توانید در Task list summary in the Pull Request list. ببینید.

Example Task List
نمودار 104. Task list summary in the Pull Request list.

این قابلیت‌ها وقتی که زود یک Pull Request باز می‌کنید و از آن برای پیگیری پیشرفت پیاده‌سازی یک ویژگی استفاده می‌کنید، فوق‌العاده کاربردی هستند.

Code Snippets (قطعه‌های کد)

شما می‌توانید قطعه‌های کد را هم به نظرات اضافه کنید. این موضوع به‌ویژه زمانی مفید است که بخواهید چیزی را نشان دهید که می‌توانید قبل از اینکه واقعاً آن را به‌صورت کامیت در شاخه‌تان پیاده‌سازی کنید، امتحان کنید. همچنین اغلب برای افزودن نمونه کدی استفاده می‌شود که نشان می‌دهد چه چیزی کار نمی‌کند یا این Pull Request چه چیزی را می‌تواند پیاده کند.

برای اضافه کردن یک قطعه کد، باید آن را بین سه علامت بک‌تیک (```) قرار دهید.

```java
for(int i=0 ; i < 5 ; i++)
{
   System.out.println("i is : " + i);
}
```

اگر مانند مثالی که زدیم نام یک زبان برنامه‌نویسی مثل java را هم اضافه کنید، گیت‌هاب تلاش می‌کند قطعه کد را با رنگ‌بندی نحو (syntax highlighting) نمایش دهد. در مثال بالا، نتیجه به شکل Rendered fenced code example. خواهد بود.

Rendered fenced code
نمودار 105. Rendered fenced code example.

Quoting (کوت کردن)

اگر می‌خواهید به بخش کوچکی از یک کامنت طولانی پاسخ دهید، می‌توانید آن بخش را به صورت انتخابی نقل‌قول کنید؛ کافی است خط‌ها را با علامت > شروع کنید. در واقع، این کار آنقدر رایج و کاربردی است که یک میانبر صفحه‌کلید برایش وجود دارد. اگر متنی را در یک کامنت انتخاب کنید که می‌خواهید مستقیماً به آن جواب بدهید و کلید r را بزنید، آن متن به صورت نقل‌قول در کادر پاسخ برایتان قرار می‌گیرد.

نقل‌قول‌ها به شکلی شبیه به این خواهند بود:

> Whether 'tis Nobler in the mind to suffer
> The Slings and Arrows of outrageous Fortune,

How big are these slings and in particular, these arrows?

وقتی نمایش داده شود، کامنت به شکل Rendered quoting example. خواهد بود.

Rendered quoting
نمودار 106. Rendered quoting example.

Emoji (ایموجی)

در نهایت، می‌توانید از ایموجی‌ها هم در نظرات خود استفاده کنید. این موضوع در بسیاری از کامنت‌هایی که در Issue ها و Pull Request های گیت‌هاب می‌بینید، به طور گسترده استفاده می‌شود. گیت‌هاب حتی یک ابزار کمکی برای ایموجی‌ها دارد. وقتی در حال نوشتن نظر هستید و با کاراکتر : شروع کنید، سیستم تکمیل خودکار به شما کمک می‌کند ایموجی مورد نظرتان را سریع پیدا کنید.

Emoji autocompleter
نمودار 107. Emoji autocompleter in action.

ایموجی‌ها در هر جایی از کامنت به شکل :<name>: نوشته می‌شوند. برای مثال، می‌توانید چیزی شبیه به این بنویسید:

I :eyes: that :bug: and I :cold_sweat:.

:trophy: for :microscope: it.

:+1: and :sparkles: on this :ship:, it's :fire::poop:!

:clap::tada::panda_face:

وقتی نمایش داده شود، چیزی شبیه به Heavy emoji commenting. خواهد بود.

Emoji
نمودار 108. Heavy emoji commenting.
یادداشت

امروزه در واقع تعداد زیادی از سرویس‌های وب از کاراکترهای ایموجی استفاده می‌کنند. یک برگه تقلب (cheat sheet) عالی برای پیدا کردن ایموجی‌هایی که منظور شما را به‌خوبی بیان می‌کنند، در اینجا قابل دسترسی است:

Images (عکس ها)

این مورد از نظر فنی بخشی از Markdown مخصوص گیت‌هاب (GitHub Flavored Markdown) نیست، اما فوق‌العاده کاربردی است. علاوه بر افزودن لینک تصاویر به کامنت‌ها با استفاده از Markdown — که پیدا کردن و جاسازی URL آن‌ها می‌تواند دشوار باشد — گیت‌هاب این امکان را فراهم کرده که تصاویر را مستقیماً به داخل بخش‌های متنی بکشید و رها کنید (drag & drop) تا به‌صورت خودکار در متن جاسازی شوند.

تصاویر را بکشید و رها کنید (Drag & Drop) تا آپلود شده و به‌صورت خودکار در متن جاسازی (Embed) شوند. image::images/markdown-08-drag-drop.png[Drag and drop images]

اگر به [_md_drag] نگاه کنید، می‌توانید یک راهنمای کوچک با عنوان «Parsed as Markdown» را در بالای ناحیه‌ی متنی ببینید. با کلیک روی آن، یک برگه تقلب کامل (cheat sheet) از تمام قابلیت‌هایی که می‌توانید با Markdown در گیت‌هاب انجام دهید نمایش داده می‌شود.

Keep your GitHub public repository up-to-date (مخزن عمومی گیت‌هاب خود را به‌روز نگه دارید)

پس از آن‌که یک مخزن (repository) را در گیت‌هاب fork کردید، مخزن شما (که به آن "fork" گفته می‌شود) به‌صورت مستقل از مخزن اصلی عمل می‌کند. به‌ویژه، زمانی که مخزن اصلی commit های جدیدی داشته باشد، گیت‌هاب با پیامی شبیه به این شما را مطلع می‌کند:

This branch is 5 commits behind progit:master.

اما مخزن شما در گیت‌هاب هرگز به‌صورت خودکار توسط گیت‌هاب به‌روزرسانی نمی‌شود؛ این کاری است که باید خودتان انجام دهید. خوشبختانه، انجام این کار بسیار ساده است.

یکی از روش‌هایی که نیاز به هیچ‌گونه پیکربندی ندارد، به‌این صورت است: برای مثال، اگر مخزن را از https://github.com/progit/progit2.git fork کرده‌اید، می‌توانید شاخه‌ی master خود را به این شکل به‌روز نگه دارید:

$ git checkout master (1)
$ git pull https://github.com/progit/progit2.git (2)
$ git push origin master (3)
  1. اگر روی شاخه‌ای (branch) دیگر هستید، به master برگردید.

  2. تغییرات را از https://github.com/progit/progit2.git دریافت (fetch) کرده و در master ادغام (merge) کنید.

  3. شاخه‌ی master خود را به origin پوش (push) کنید.

این روش کار می‌کند، اما وارد کردن دستی آدرس fetch در هر بار، کمی خسته‌کننده است. می‌توانید این کار را با کمی پیکربندی به‌صورت خودکار انجام دهید:

$ git remote add progit https://github.com/progit/progit2.git (1)
$ git branch --set-upstream-to=progit/master master (2)
$ git config --local remote.pushDefault origin (3)
  1. مخزن منبع (source repository) را اضافه کنید و به آن یک نام بدهید. در اینجا، من نام progit را انتخاب کرده‌ام.

  2. شاخه‌ی master خود را تنظیم کنید تا از ریموت progit تغییرات را دریافت (fetch) کند.

  3. مخزن پیش‌فرض برای push را روی origin قرار دهید.

بعد از انجام این تنظیمات، روند کار بسیار ساده‌تر می‌شود:

$ git checkout master (1)
$ git pull (2)
$ git push (3)
  1. اگر روی شاخه‌ای دیگر هستید، به master برگردید.

  2. تغییرات را از progit دریافت (fetch) کرده و با شاخه‌ی master ادغام (merge) کنید.

  3. شاخه‌ی master خود را به origin پوش (push) کنید.

این روش می‌تواند مفید باشد، اما بدون مشکلات نیست. گیت این کار را به‌صورت خودکار و بی‌صدا انجام می‌دهد، اما اگر به شاخه‌ی master مستقیماً commit بزنید، سپس از progit pull بگیرید و بعد به origin push کنید، به شما هشدار نخواهد داد — همه این عملیات‌ها در این تنظیمات معتبر هستند. پس باید مراقب باشید که هرگز مستقیم روی master کامیت نزنید، چون این شاخه عملاً متعلق به مخزن upstream است.

scroll-to-top